﻿using System;
using System.Windows.Forms;
using RSPJ.Struct;
using RSPJ.Windows;

namespace RSPJ.Function
{
    public class funcStatistics
    {
        // 总体平均值
        public Files Mean(Files file)
        {
            Files outFile = file.Clone();
            outFile.Name = "Mean:" + outFile.Name;
            outFile.Head.Bands = 1;
            outFile.Head.Interleave = "bsq";
            outFile.IntArray = new double[1, file.Head.Lines, file.Head.Samples];

            //计算均值
            for (int j = 1; j < file.Head.Lines - 1; j++)
            {
                for (int k = 1; k < file.Head.Samples - 1; k++)
                {
                    for (int i = 0; i < file.Head.Bands; i++)
                    {
                        outFile.IntArray[0, j, k] += file.IntArray[i, j, k];
                    }
                    outFile.IntArray[0, j, k] /= file.Head.Bands;
                }
            }
            return outFile;
        }

        // 总体标准差
        public Files StandardDeviation(Files file)
        {
            Files outFile = file.Clone();
            outFile.Name = "StandardDeviation:" + outFile.Name;
            outFile.Head.Bands = 1;
            outFile.Head.Interleave = "bsq";
            outFile.IntArray = new double[1, file.Head.Lines, file.Head.Samples];

            //计算标准差
            for (int j = 1; j < file.Head.Lines - 1; j++)
            {
                for (int k = 1; k < file.Head.Samples - 1; k++)
                {
                    double ex = 0, ex2 = 0;
                    for (int i = 0; i < file.Head.Bands; i++)
                    {
                        ex += file.IntArray[i, j, k];
                        ex2 += Math.Pow(file.IntArray[i, j, k], 2);
                    }
                    ex /= 9;
                    ex2 /= 9;

                    outFile.IntArray[0, j, k] = (int)Math.Sqrt(ex2 - Math.Pow(ex, 2));
                }
            }

            return outFile;
        }

        // 极差纹理
        public Files Extreme(Files file)
        {
            Files outFile = file.Clone();
            outFile.Name = "StandardDeviation:" + outFile.Name;
            outFile.Head.Bands = 1;
            outFile.Head.Interleave = "bsq";
            outFile.IntArray = new double[1, file.Head.Lines, file.Head.Samples];


            for (int i = 0; i < file.Head.Bands; i++)
            {
                for (int j = 1; j < file.Head.Lines - 1; j++)
                {
                    for (int k = 1; k < file.Head.Samples - 1; k++)
                    {
                        double max = file.IntArray[i, j, k], min = file.IntArray[i, j, k];
                        for (int m = j - 1; m <= j + 1; m++)
                        {
                            for (int n = k - 1; n <= k + 1; n++)
                            {
                                if (file.IntArray[i, m, n] > max)
                                    max = file.IntArray[i, m, n];
                                if (file.IntArray[i, m, n] < min)
                                    min = file.IntArray[i, m, n];
                            }
                        }
                        outFile.IntArray[i, j, k] = max - min;
                    }
                }
            }

            return outFile;
        }

        // 单波段均值
        public double[] MeanSingle(Files file)
        {
            double[] ex = new double[file.Head.Bands];

            for (int i = 0; i < file.Head.Bands; i++)
            {
                ex[i] = 0;
            }

            for (int i = 0; i < file.Head.Bands; i++)
            {
                for (int j = 0; j < file.Head.Lines; j++)
                    for (int k = 0; k < file.Head.Samples; k++)
                    {
                        ex[i] += file.IntArray[i, j, k];
                    }
                ex[i] /= (file.Head.Lines * file.Head.Samples);
            }

            return ex;
        }

        // 单波段标准差
        public double[] StandardSingle(Files file)
        {
            double[] ex = new double[file.Head.Bands];
            double[] ex2 = new double[file.Head.Bands];
            double[] dx = new double[file.Head.Bands];

            for (int i = 0; i < file.Head.Bands; i++)
            {
                ex[i] = 0;
                ex2[i] = 0;
                dx[i] = 0;
            }

            for (int i = 0; i < file.Head.Bands; i++)
            {
                for (int j = 0; j < file.Head.Lines; j++)
                    for (int k = 0; k < file.Head.Samples; k++)
                    {
                        ex[i] += file.IntArray[i, j, k];
                        ex2[i] += Math.Pow(file.IntArray[i, j, k], 2);
                    }
                ex[i] /= (file.Head.Lines * file.Head.Samples);
                ex2[i] /= (file.Head.Lines * file.Head.Samples);
                dx[i] = Math.Sqrt(ex2[i] - Math.Pow(ex[i], 2));
            }

            return dx;
        }

        // 协方差矩阵
        public double[,] Covariance(Files file)
        {
            double[,] Cov = new double[file.Head.Bands, file.Head.Bands];
            double[] ex = new double[file.Head.Bands];

            //初始化
            for (int i = 0; i < file.Head.Bands; i++)
            {
                for (int j = 0; j < file.Head.Bands; j++)
                {
                    Cov[i, j] = 0;
                }
                ex[i] = 0;
            }

            //计算协方差
            for (int i = 0; i < file.Head.Bands; i++)
            {
                for (int j = 0; j < file.Head.Lines; j++)
                    for (int k = 0; k < file.Head.Samples; k++)
                    {
                        ex[i] += file.IntArray[i, j, k];
                    }
                ex[i] /= (file.Head.Lines * file.Head.Samples);
            }

            for (int m = 0; m < file.Head.Bands; m++)
            {
                for (int n = 0; n < file.Head.Bands; n++)
                {
                    for (int j = 0; j < file.Head.Lines; j++)
                    {
                        for (int k = 0; k < file.Head.Samples; k++)
                        {
                            Cov[m, n] += (file.IntArray[m, j, k] - ex[m]) * (file.IntArray[n, j, k] - ex[n]);
                        }
                    }
                    Cov[m, n] /= (file.Head.Lines * file.Head.Samples);
                }
            }

            //显示协方差矩阵
            return Cov;
        }

        // 相关系数矩阵
        public double[,] CorrelationCoefficient(Files file)
        {
            double[,] Cov = new double[file.Head.Bands, file.Head.Bands];
            double[] ex = new double[file.Head.Bands];
            double[] ex2 = new double[file.Head.Bands];
            double[] dx = new double[file.Head.Bands];//这里指标准差
            double[,] Cor = new double[file.Head.Bands, file.Head.Bands];//相关系数

            //初始化
            for (int i = 0; i < file.Head.Bands; i++)
            {
                for (int j = 0; j < file.Head.Bands; j++)
                {
                    Cov[i, j] = 0;
                }
                ex[i] = 0;
                ex2[i] = 0;
            }

            //计算标准差
            for (int i = 0; i < file.Head.Bands; i++)
            {
                for (int j = 0; j < file.Head.Lines; j++)
                    for (int k = 0; k < file.Head.Samples; k++)
                    {
                        ex[i] += file.IntArray[i, j, k];
                        ex2[i] += Math.Pow(file.IntArray[i, j, k], 2);
                    }
                ex[i] /= (file.Head.Lines * file.Head.Samples);
                ex2[i] /= (file.Head.Lines * file.Head.Samples);
                dx[i] = Math.Sqrt(ex2[i] - Math.Pow(ex[i], 2));
            }

            //计算协方差
            for (int m = 0; m < file.Head.Bands; m++)
            {
                for (int n = 0; n < file.Head.Bands; n++)
                {
                    for (int j = 0; j < file.Head.Lines; j++)
                    {
                        for (int k = 0; k < file.Head.Samples; k++)
                        {
                            Cov[m, n] += (file.IntArray[m, j, k] - ex[m]) * (file.IntArray[n, j, k] - ex[n]);
                        }
                    }
                    Cov[m, n] /= (file.Head.Lines * file.Head.Samples);
                }
            }

            //计算相关系数
            for (int i = 0; i < file.Head.Bands; i++)
                for (int j = 0; j < file.Head.Bands; j++)
                {
                    Cor[i, j] = Cov[i, j] / (dx[i] * dx[j]);
                }

            return Cor;
        }

        // 计算共生矩阵
        public int[,] SymbioticMatrix(Files file)
        {
            int a, b;
            int[,] F = new int[256, 256];
            using (SymbioticMatrixParameter sm = new SymbioticMatrixParameter())
            {
                if (sm.ShowDialog() == DialogResult.OK)
                {
                    a = sm.a;
                    b = sm.b;
                    for (int u = 0; u <= 255; u++)
                    {
                        for (int v = 0; v <= 255; v++)
                        {
                            F[u, v] = 0;
                        }
                    }

                    int u0, v0;

                    for (int i = 0; i < file.Head.Bands; i++)
                    {
                        for (int j = 0; j + b < file.Head.Lines; j++)
                        {
                            for (int k = 0; k + a < file.Head.Samples; k++)
                            {
                                u0 = (int)file.IntArray[i, j, k];
                                v0 = (int)file.IntArray[i, j + b, k + a];
                                F[u0, v0]++;
                            }
                        }
                    }
                }
            }
            return F;
        }

        // 计算对比度
        public int Contrast(Files file)
        {
            int contrast = 0;
            int[,] F = SymbioticMatrix(file);
            for (int u = 0; u <= 255; u++)
            {
                for (int v = 0; v <= 255; v++)
                {
                    contrast += (u - v) * (u - v) * F[u, v];
                }
            }
            return contrast;
        }

        // 计算直方图
        public void funcHistogram()
        {
            using (SelectBands sb = new SelectBands(1))
            {
                if (sb.ShowDialog() == DialogResult.OK)
                {
                    string filename = sb.FileBand;
                    int band = sb.Band;
                    Histogram h = new Histogram(filename, band, 1);
                    h.Show();
                }
            }
        }

        // 计算累计直方图
        public void CumuHistogram()
        {
            using (SelectBands sb = new SelectBands(1))
            {
                if (sb.ShowDialog() == DialogResult.OK)
                {
                    string filename = sb.FileBand;
                    int band = sb.Band;
                    Histogram h = new Histogram(filename, band, 2);
                    h.Show();
                }
            }
        }

        // 计算联合直方图
        public int[,] JointHistogram()
        {
            int[,] b = new int[256, 256];
            using (SelectBands sb = new SelectBands(2))
            {
                if (sb.ShowDialog() == DialogResult.OK)
                {
                    string file1 = sb.File1;
                    string file2 = sb.File2;
                    int band1 = sb.Band1;
                    int band2 = sb.Band2;
                    int lines = sb.lines;
                    int samples = sb.samples;

                    Files f1 = new Files();
                    Files f2 = new Files();

                    for (int i = 0; i < GlobalData.fileList.Count; i++)
                    {
                        if (file1 == GlobalData.fileList[i].Name)
                            f1 = GlobalData.fileList[i].Clone();
                        if (file2 == GlobalData.fileList[i].Name)
                            f2 = GlobalData.fileList[i].Clone();
                    }

                    for (int j = 0; j < lines; j++)
                    {
                        for (int k = 0; k < samples; k++)
                        {
                            b[(int)f1.IntArray[band1 - 1, j, k], (int)f2.IntArray[band2 - 1, j, k]]++;
                        }
                    }
                }

                return b;
            }
        }

        // 计算频率
        public int[,] Frequency(Files file)
        {
            int[,] frestr = new int[10, 256];

            for (int i = 0; i < file.Head.Bands; i++)
            {
                for (int j = 0; j < file.Head.Lines; j++)
                {
                    for (int k = 0; k < file.Head.Samples; k++)
                    {
                        frestr[i, (int)file.IntArray[i, j, k]]++;
                    }
                }
            }
            return frestr;
        }
    }
}
